#!/usr/bin/env python 
# coding:utf-8
# @Time :10/9/18 16:23


import threading
import time

from beanstalkc import SocketError, CommandFailed

from common.pybeanstalk import PyBeanstalk
from config.beanstalk_conf import BEANSTALK_CONF

from Queue import Queue


class Mqhandle(threading.Thread):
    # 最大待发送消息队列大小
    __MAX_QUEUE_NUMBER = 50

    def __init__(self, tube, log, max_beanstalk_block=100):
        threading.Thread.__init__(self)
        self.logger = log
        self.__beanstalk = PyBeanstalk(BEANSTALK_CONF["host"], BEANSTALK_CONF['port'])
        self.__tube = tube
        self.__queue = Queue()
        self.__is_runing = True
        self.__max_beanstalk_block = max_beanstalk_block
        self.start()

    @property
    def current_queue_size(self):
        return self.__queue.qsize()

    def __is_queue_block(self):
        return True if self.__queue.qsize() >= self.__MAX_QUEUE_NUMBER else False

    def push_to_queue(self, item_dict):

        if not self.__is_runing:
            self.logger.error("Mqhandle push_to_queue 当前消息队列没有正常工作")
            return False

        self.__queue.put_nowait(item_dict)

        if self.__is_queue_block():
            self.logger.warn("当前队列阻塞...")
            return False
        return True

    # 判断beanstalk消息队列是否堵塞
    def __is_beanstalk_block(self, tube):
        while True:
            sleep_count = 0
            try:
                count = self.__beanstalk.get_tube_count(tube)
            except CommandFailed, (_, status, results):
                if status == 'NOT_FOUND':
                    self.logger.error('获取消息队列不存在: tube = {}'.format(tube))
                    count = 0
                else:
                    self.logger.error('获取消息队列异常: tube = {} status = {}'.format(tube, status))
                    count = self.__max_beanstalk_block
            except Exception as e:
                count = self.__max_beanstalk_block
                self.logger.error("获取消息队列大小失败: ")
                self.logger.exception(e)

            if count >= self.__max_beanstalk_block:
                time.sleep(1)
                sleep_count += 1
                if sleep_count % 100 == 0:
                    self.logger.warning("__is_beanstalk_block 已经阻塞了 %s s了" % sleep_count)
                continue
            return True

    def close(self):
        self.__is_runing = False

    def run(self):
        self.logger.info('开始运行消息队列...')
        while self.__is_runing:
            try:

                body = self.__queue.get()

                # if self.__is_beanstalk_block(self.__tube):
                #     continue

                if not isinstance(body, basestring):
                    self.logger.error("消息类型错误: body type = {} msg = {}".format(type(body), body))
                    continue

                while True:
                    try:
                        result = self.__beanstalk.put(self.__tube, body)
                        if not result:
                            self.logger.error("数据量太大: msg len = {}".format(len(body)))
                        break
                    except SocketError as e:
                        time.sleep(10)
                        self.__beanstalk.reconnect()
                        self.logger.warn("reconnect beanstalk...")
                        self.logger.exception(e)
                    except Exception as e:
                        self.logger.error('捕获异常休眠:')
                        self.logger.exception(e)
                        time.sleep(10)

            except BaseException as e:
                self.logger.info('当前队列大小: size = {size}'.format(size=self.__queue.qsize()))
                self.logger.exception(e)
                time.sleep(5)

        self.logger.info("消息队列正常退出...")
